#include "BasicSolver.hpp"
#include <cstdlib>

void	BasicSolver::execute() EXC_THROWER()
{	
	EXC_RETHROW_BEGIN()
	{
		std::multimap<double, unsigned>::const_iterator	it;
		unsigned									index_tournee = 0;
		TourneeEvalResult							tournee_evalres;
		std::map<unsigned, unsigned>				clients_served;
		unsigned									index_client = 0;
		unsigned									index_previous = 0;
		
		clients_served[DEPOT] = 0xdeb1e;
		clients_served[100] = 0xdeb1e;
		
		s.clear();
		while (!s.isComplete())
		{
			memset(&tournee_evalres, 0, sizeof(tournee_evalres));
			Tournee&	tournee = s[index_tournee];
			
			it = soVRPTW.getDistanceByClient(DEPOT).begin();
						
			while ((clients_served.find(it->second)) != clients_served.end())
			{
				++it;
			}
			
			if (it == soVRPTW.getDistanceByClient(DEPOT).end())
				break;
			
			//std::cout << "index tournee : " << index_tournee << " starting with client " << it->second << std::endl;
			
			if (clients_served.size() == 102)
				break;
			
			for(;;)
			{	
				index_client = it->second;
				
				//std::cout << "trying to insert " << it->second;
				
				// inserer le client le plus proche
				tournee.insertClient(Tournee::INSERT_END, it->second);
				tournee.eval(&tournee_evalres);
				
				// si tournee valide
				if (tournee_evalres.erValable)
				{
					//std::cout << " VALID" << std::endl;
					//getchar();
					
					// alors le client est servi
					clients_served[it->second] = 0xdeb1e;
					
					index_previous = index_client;
					
					// on fixe le client suivant comme etant le client le plus proche
					// qui n'a pas ete servi
					it = soVRPTW.getDistanceByClient(index_client).begin();
					while ((clients_served.find(it->second)) != clients_served.end())
					{
						if (it == soVRPTW.getDistanceByClient(index_client).end())
							break;
						++it;
					}
					if (it == soVRPTW.getDistanceByClient(index_client).end())
						break;
				}
				else // si tournee invalide
				{
					//std::cout << " INVALID" << std::endl;
					
					// alors on erase le client courant
					tournee.erase(index_client);
					++it;
					
					if (it == soVRPTW.getDistanceByClient(index_previous).end())
						break;
					
					// et on essaie d'en trouver un autre
					while (((clients_served.find(it->second)) != clients_served.end()))
					{
						if (it == soVRPTW.getDistanceByClient(index_previous).end())
							break;
						++it;
					}						
					// si on a atteint la fin
					// la tournee est terminee, il faut en ouvrir une nouvelle
					if (it == soVRPTW.getDistanceByClient(index_previous).end())
						break;
				}
				
				
			}
			
			//std::cout << s.toString() << std::endl;
			s.validateTournee(index_tournee);
			index_tournee++;
		}
		
		if (!s.isComplete())
			s.complete();
		soBestSolution = &s;
		//std::cout << s.toString() << std::endl;
	}
	EXC_RETHROW_END()
}
